import KoaRouter from 'koa-router'
import Config from '@/config/Config'
import verifyToken from '@/middlewares/verifyToken'
import { Models } from '@/common/typings/modle'
import { HttpException, ParameterException, Success } from '@/core/HttpException'
import validator from '@/middlewares/validator'
import schema from '@/common/api-json-schema/upload/uploadFile'
import getCosInstance from '@/server/cos'
import { generateRandomString, parseFileName } from '@/common/utils/string'
import { command } from '@/server/mysql'
import { addInsert, getFields, getFieldValues } from '@/common/utils/sql'

const path = require('path')
const fs = require('fs')

const router = new KoaRouter({
  prefix: `${Config.API_PREFIX}cos`,
})
const clients = new Map()
router.get('/getFile', async (ctx: Models.Ctx) => {
  const fileId = ctx.query.fileId
  if (!fileId) {
    throw new ParameterException()
  }
  const list: any[] = (await command(`SELECT obj_key FROM v3_cos WHERE file_id = '${fileId}';`, true)).results
  if (list.length !== 1) {
    throw new HttpException({ msg: '数据异常' })
  }
  const key = list[0].objKey
  const cos = getCosInstance()
  let res
  try {
    res = await new Promise((resolve, reject) => {
      cos.getObjectUrl(
        {
          Bucket: Config.COS_CONFIG.Bucket, // 填入您自己的存储桶，必须字段
          Region: Config.COS_CONFIG.Region, // 存储桶所在地域，例如 ap-beijing，必须字段
          Key: key, // 存储在桶里的对象键（例如1.jpg，a/b/test.txt），必须字段
          Expires: 3600, // 链接有效时间(秒)
          Sign: true,
        },
        function (err, data) {
          if (err) {
            reject(err)
          } else {
            resolve(data.Url)
          }
        },
      )
    })
  } catch (e) {
    throw new HttpException({ msg: '获取文件报错:' + JSON.stringify(e) })
  }
  throw new Success({
    data: res,
    msg: 'ok',
    code: 200,
    errorCode: 0,
  })
})
// 此方法总是有点问题，暂时不使用
router.get('/uploadFileProgress', async (ctx: Models.Ctx) => {
  console.log('监听SSE流')
  const taskId = ctx.query.taskId
  if (!taskId) {
    // ctx.body = {msg: '未获取到参数taskId', errorCode: -2}
    ctx.res.write(
      `data: ${JSON.stringify({
        errorCode: -2,
        msg: '未获取到参数taskId',
      })}\n\n`,
    )
    ctx.res.end()
    return
  }
  ctx.set({
    'Content-Type': 'text/event-stream',
    'Cache-Control': 'no-cache',
    Connection: 'keep-alive',
  })
  ctx.status = 200
  // 新客户端连接
  const client = {
    id: Date.now(),
    ctx,
  }
  clients.set(taskId, client)

  // ctx.res.write(JSON.stringify({ percent: 0, isInit: true }));
  console.log('发送初始状态')
  ctx.res.write(
    `data: ${JSON.stringify({
      isInit: true,
    })}\n\n`,
  )

  const heartbeatInterval = setInterval(() => {
    if (ctx.res.writable) {
      ctx.res.write(': heartbeat\n\n')
    }
  }, 30000)

  // 连接关闭时清理
  ctx.req.on('close', () => {
    console.log('监听到close')
    clearInterval(heartbeatInterval)
    clients.delete(taskId)
  })
})
router.post('/uploadFile', verifyToken, validator(schema, 'body'), async (ctx: Models.Ctx) => {
  const params: any = ctx.request.body
  // const taskId = params.taskId
  const businessDir = params.businessDir
  // console.log('taskId', taskId)
  const file: any = ctx.request.files.file
  if (!file) {
    throw new ParameterException()
  }
  // filepath: '/Users/fuyongbo/Documents/webstormWorkspace/example/admin-system/back-system/uploads/1c4182cea8515703654a0f301.crt.vue',
  //   newFilename: '1c4182cea8515703654a0f301.crt.vue',
  //   originalFilename: 'template.crt.vue',
  //   mimetype: 'application/octet-stream',
  // size: 54698,
  const fileSuffix = parseFileName(file.originalFilename).suffix
  const filePath = file.filepath
  const fileName = file.originalFilename

  // 存储一条记录
  const fileId = generateRandomString()
  const objKey = `${businessDir}${businessDir.endsWith('/') ? '' : '/'}${fileId}${fileSuffix ? `.${fileSuffix}` : ''}`
  const fieldObj = {
    fileId,
    objKey,
    fileName,
  }
  const result = (
    await command(
      addInsert(`INSERT INTO v3_cos
 (${getFields(fieldObj)})
  values
   (${getFieldValues(fieldObj)}
   );`),
      true,
    )
  ).results
  if (result.affectedRows !== 1) {
    throw new HttpException()
  }

  const cos = getCosInstance()
  // console.log('clients:', clients)
  // const client: any = clients.get(taskId)
  // console.log('client:', client)
  let res
  try {
    res = await new Promise((resolve, reject) => {
      cos.putObject(
        {
          Bucket: Config.COS_CONFIG.Bucket, // 填入您自己的存储桶，必须字段
          Region: Config.COS_CONFIG.Region, // 存储桶所在地域，例如 ap-beijing，必须字段
          Key: objKey, // 存储在桶里的对象键（例如1.jpg，a/b/test.txt），必须字段
          // 当 Body 为 stream 类型时，ContentLength 必传，否则 onProgress 不能返回正确的进度信息
          Body: fs.createReadStream(filePath), // 上传文件对象，必须字段
          ContentLength: fs.statSync(filePath).size,
          // onProgress: function (progressData) {
          // console.log('发送上传进度状态', progressData, client)
          // 当前进度： {"loaded":0,"total":54698,"speed":0,"percent":0}
          // 当前进度： {"loaded":54698,"total":54698,"speed":83254.19,"percent":1}
          // console.log('当前进度：', JSON.stringify(progressData));
          // if (client) {
          //   client.ctx.res.write(`data: ${JSON.stringify({
          //     taskId,
          //     progressData
          //   })}\n\n`)
          // }
          // client.ctx.body = JSON.stringify({
          //   taskId,
          //   percent: progressData.percent * 100, // 百分比
          //   loaded: progressData.loaded,          // 已上传字节
          //   total: progressData.total             // 总字节
          // })
          // client.ctx.flushHeaders();
          // 删除临时文件
          // fs.unlink(filePath, (unlinkErr) => {
          //   if (unlinkErr) console.error("删除失败", unlinkErr);
          //   else console.log("临时文件已清理");
          // });
          // }
        },
        function (err, data) {
          if (err) {
            // console.log('上传失败', err);
            reject(err)
            // ctx.body = {msg: '上传失败', errorCode: -1};
            // clients.get(taskId).ctx.body = JSON.stringify({ taskId, msg: err.message });
          } else {
            // 上传成功 {
            //   statusCode: 200,
            //     headers: {
            //     'content-length': '0',
            //       connection: 'keep-alive',
            //       date: 'Fri, 22 Aug 2025 08:58:01 GMT',
            //       etag: '"5595deca2cf04486e303fa346fe3e5fd"',
            //       server: 'tencent-cos',
            //       'x-cos-hash-crc64ecma': '4923350317894988105',
            //       'x-cos-request-id': 'NjhhODMxMTlfODkyZjlhMWVfMjVlZWZfNDU4MWQ4Yg==',
            //       'x-cos-storage-class': 'STANDARD'
            //   },
            //   Location: 'fuybooo-1375083581.cos.ap-guangzhou.myqcloud.com/fuybooo',
            //     ETag: '"5595deca2cf04486e303fa346fe3e5fd"',
            //     RequestId: 'NjhhODMxMTlfODkyZjlhMWVfMjVlZWZfNDU4MWQ4Yg=='
            // }

            // console.log('上传成功', data);
            // clients.get(taskId).ctx.body = JSON.stringify({ taskId, url: data.Location })
            // ctx.body = {msg: '上传成功', errorCode: 0, data: fileId};
            // 删除临时文件
            fs.unlink(filePath, (unlinkErr) => {
              if (unlinkErr) console.error('删除失败', unlinkErr)
              else console.log('临时文件已清理')
            })
            resolve(data)
          }
        },
      )
    })
  } catch (e) {
    throw new HttpException({ msg: '上传失败：' + JSON.stringify(e) })
  }
  throw new Success({
    errorCode: 0,
    data: {
      fileId,
    },
    msg: '上传成功',
  })
})
export default router
